package fem2.observer;

import java.io.IOException;
import java.util.ArrayList;

import fem2.Debugger;
import fem2.Element;
import fem2.Model;
import fem2.element.StructuralElement;
import fem2.material.TopOptMaterialModel;

/**
 * TODO
 * 
 * @author hbui
 * 
 */
public class GidTopOptDensityObserver extends GidStructuralObserver {

	private double timeStep = 0.0;

	public GidTopOptDensityObserver(Model m, TimeStepObserver o, String projectDir,
			String projectName) {
		super(m, o, projectDir, projectName);
	}

	public GidTopOptDensityObserver(Model m, TimeStepObserver o, String projectDir,
			String projectName, String fileName) {
		super(m, o, projectDir, projectName, fileName);
	}

	@Override
	public void fireStarted() {
	}

	@Override
	public void fireTimeStepStarted() {
	}

	@Override
	public void fireIterationStarted() {
	}

	@Override
	public void fireIterationFinished() {
	}

	@Override
	public void fireTimeStepFinished() {
		if (gidPost != null) {
			timeStep += 1.0;
			for (String elementType : m.getElementTypes()) {
				ArrayList<Integer> elemIdList = new ArrayList<Integer>();
				ArrayList<Double> listValues = new ArrayList<Double>();
				for (int i = 0; i < m.countElements(); i++) {
					Element e = m.getElement(i);
					if (e.getElemType().equals(elementType)) {
						elemIdList.add(e.getId());
						if (e instanceof StructuralElement) {
							StructuralElement se = (StructuralElement) e;
							if (se.getMaterialModel() instanceof TopOptMaterialModel) {
								TopOptMaterialModel topmm = (TopOptMaterialModel) se
										.getMaterialModel();
								listValues.add(topmm.getElementDensity(e));
							} else {
								listValues.add(0.0);
							}
						} else {
							listValues.add(0.0);
						}
					}
				}

				String variableName = "DENSITY";
				int[] elemIds = new int[elemIdList.size()];
				double[][] values = new double[elemIdList.size()][1];
				for (int i = 0; i < elemIdList.size(); i++) {
					elemIds[i] = elemIdList.get(i);
					values[i][0] = listValues.get(i);
				}
				try {
					gidPost.writeMesh(m, timeStep);
					String groupName = "density_gp_" + elementType;
					gidPost.writeGausspointScalarResult(variableName, groupName, elementType,
							elemIds, values, timeStep);
				} catch (IOException e) {
					throw new Error("Write failed: " + e.getMessage());
				}
			}
		}
	}

	@Override
	public void fireFinished() {
		for (int i = 0; i < m.countElements(); i++) {
			Element e = m.getElement(i);
			if (e instanceof StructuralElement) {
				if (((StructuralElement) e).getMaterialModel() instanceof TopOptMaterialModel) {
					TopOptMaterialModel mm = (TopOptMaterialModel) ((StructuralElement) e)
							.getMaterialModel();
					Debugger.watch("Element " + e.getId() + " density = " + mm.getElementDensity(e));
				}
			}
		}
	}

}
